package com.szxy.consumer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @Author: zwz
 * @Date:2020/7/1 17:11
 * @Description:com.szxy.consumer
 * @Version:1.0
 **/
@SpringBootApplication
@EnableDiscoveryClient // 开启服务注册与发现
@RestController

public class ConsumerServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerServerApplication.class, args);
    }

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/discovery/{serverId}")
    public ResponseEntity discoveryList(@PathVariable String serverId) {
        List<ServiceInstance> instances = this.discoveryClient.getInstances(serverId);
        if (null == instances || instances.isEmpty()) {
            // 404
            return ResponseEntity.ok("empty");
        }
        List<String> serverList = new ArrayList<>();
        instances.forEach(instance -> serverList.add(instance.getHost() + ":" + instance.getPort()));
        return ResponseEntity.ok(serverList);
    }

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 将 restTemplate 纳入 Spring IOC 容器中
     *
     * @return
     */
    @LoadBalanced
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }


    /**
     * 远程调用测试
     * @param message 参数
     * @return
     */
    @GetMapping("/rpc1/{message}")
    public ResponseEntity rpv1(@PathVariable String message) {
        ResponseEntity<String> responseEntity = null;
        try{
            responseEntity = this.restTemplate.getForEntity(
                    // 调用服务的 url 地址
                    "http://localhost:8081/echo/" + message,
                    // 调用服务的返回值类型
                    String.class
            );
        }catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.badRequest().body("远程调用失败");
        }
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            return ResponseEntity.ok("远程调用成功，内容为：" + responseEntity.getBody());
        }
        return ResponseEntity.badRequest().body("远程调用失败");
    }


    /**
     * 远程调用测试2
     * @param message 参数
     * @return
     */
    @GetMapping("/rpc2/{message}")
    public ResponseEntity rpv2(@PathVariable String message) {
        List<ServiceInstance> instances = this.discoveryClient.getInstances("service-provider");
        ServiceInstance serviceInstance = instances.get(0);
        ResponseEntity<String> responseEntity = null;
        try{
            responseEntity = this.restTemplate.getForEntity(
                    // 调用服务的 url 地址
                    String.format("http://%s/echo/%s", serviceInstance.getHost()+":"+serviceInstance.getPort(), message),
                    // 调用服务的返回值类型
                    String.class
            );
        }catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.badRequest().body("远程调用失败");
        }
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            return ResponseEntity.ok("远程调用成功，内容为：" + responseEntity.getBody());
        }
        return ResponseEntity.badRequest().body("远程调用失败");
    }


    /**
     * 远程调用测试3
     * @param message 参数
     * @return
     */
    @GetMapping("/rpc3/{message}")
    public ResponseEntity rpv3(@PathVariable String message) {
        List<ServiceInstance> instances = this.discoveryClient.getInstances("service-provider");
        ServiceInstance serviceInstance = loadBalance(instances);
        System.out.println("serviceInstance = " + serviceInstance);
        ResponseEntity<String> responseEntity = null;
        try{
            responseEntity = this.restTemplate.getForEntity(
                    // 调用服务的 url 地址
                    String.format("http://%s/echo/%s", serviceInstance.getHost()+":"+serviceInstance.getPort(), message),
                    // 调用服务的返回值类型
                    String.class
            );
        }catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.badRequest().body("远程调用失败");
        }
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            return ResponseEntity.ok("远程调用成功，内容为：" + responseEntity.getBody());
        }
        return ResponseEntity.badRequest().body("远程调用失败");
    }

    /**
     * 随机从服务列表中选取一个服务地址
     * @param instances 服务列表
     * @return
     */
    private ServiceInstance loadBalance(List<ServiceInstance> instances) {
        Random random = new Random(System.currentTimeMillis());
        return instances.get(random.nextInt(instances.size()));
    }


    /**
     * 远程调用测试4
     * @param message 参数
     * @return
     */
    @GetMapping("/rpc4/{message}")
    public ResponseEntity rpv4(@PathVariable String message) {
        ResponseEntity<String> responseEntity = null;
        try{
            responseEntity = this.restTemplate.getForEntity(
                    // 调用服务的 url 地址
                    "http://service-provider/echo/{message}",
                    // 调用服务的返回值类型
                    String.class,
                    // 参数值
                    message
            );
        }catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.badRequest().body("远程调用失败");
        }
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            return ResponseEntity.ok("远程调用成功，内容为：" + responseEntity.getBody());
        }
        return ResponseEntity.badRequest().body("远程调用失败");
    }

}
